package window;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.media.opengl.GLCapabilities;
import javax.swing.JFrame;
import javax.swing.JPanel;

import panel.canvas.CanvasPanel;
import panel.control.ControlPanel;
import panel.event.LightSelectedEvent;
import panel.event.LightSelectedListener;
import panel.event.PropertyChangedEvent;
import panel.event.PropertyChangedListener;
import panel.status.StatusPanel;
import shape.Light;
import shape.Shape;
import shape.Teapot;

public class Window extends JFrame implements ActionListener, PropertyChangedListener, LightSelectedListener {
	private GLCapabilities	capabilities;
	private List<JPanel> 	panels;

	private ControlPanel 	buttonPanel;
	private CanvasPanel 	canvasPanel;
	private StatusPanel 	statusPanel;

	public Window(){
		super("3D Editor");
		capabilities = new GLCapabilities(null);
		capabilities.setDoubleBuffered(true);

		createPanels();
		createLayout();

		pack();
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);

	}

	public void createPanels() {
		buttonPanel = new ControlPanel(this, this, this);
		statusPanel = new StatusPanel();
		canvasPanel = new CanvasPanel(capabilities);
		canvasPanel.addObserver(buttonPanel);
		canvasPanel.addObserver(statusPanel);

		buttonPanel.setPropertiesEnabled(false);

		panels = new ArrayList<JPanel>(3);
		panels.add(buttonPanel);
		panels.add(canvasPanel);
		panels.add(statusPanel);
		
		canvasPanel.addShape(new Teapot());
		try {
			canvasPanel.addLight(new Light(1, 1, 1));
		} catch (Exception e) {}
	}

	public void createLayout() {
		setLayout(new BorderLayout());
		setExtendedState(JFrame.MAXIMIZED_BOTH);

		add(canvasPanel, BorderLayout.CENTER );
		add(buttonPanel, BorderLayout.EAST );
		add(statusPanel, BorderLayout.SOUTH );
	}

	public void actionPerformed(ActionEvent e) {
		int cmd = Integer.parseInt(e.getActionCommand());

		switch (cmd) {
			case Command.ADD_SHAPE: 	generateShape(); break;
			case Command.DELETE_SHAPE: 	eraseShape(); break;
			case Command.ADD_LIGHT: 	addLight(); break;
			case Command.DELETE_LIGHT: 	removeLight(); break;
		}
		
		if (e.getSource() instanceof Component) {
			((Component) e.getSource()).transferFocus();
		}
	}

	public void propertyChanged(PropertyChangedEvent e) {
		if (e.getOp() == PropertyChangedEvent.MOVE) {
			canvasPanel.changeSelectedShapesProperty( e.getChange(), e.getIndex(), e.getProperty());
			canvasPanel.changeCameraProperty(e.getChange(), e.getIndex(), e.getProperty());
		}
		else if (e.getOp() == PropertyChangedEvent.SET) {
			canvasPanel.setSelectedShapesProperty( e.getChange(), e.getIndex(), e.getProperty());
			canvasPanel.setCameraProperty(e.getChange(), e.getIndex(), e.getProperty());
		}
	}
	
	public void lightSelected(LightSelectedEvent e) {
		canvasPanel.selectShape(e.getLight(), e.isSelected());
	}

	/* ----------------------------------------------------
	 * Response functions
	 */

	public void generateShape() {
		Shape shape = Shape.create(buttonPanel.getSelectedShapeType());
		canvasPanel.addShape(shape);
	}

	public void eraseShape() {
		canvasPanel.removeSelectedShapes();
	}
	
	public void addLight() {
		try {
			Light light = new Light();
			canvasPanel.addLight(light);
		} catch (Exception e) {
			System.out.println("[Window] ERROR: could not create light");
			System.out.println(e.getMessage());
		}
	}
	
	public void removeLight() {
		Light[] selectedLights = buttonPanel.getSelectedLights();
		for (Light light: selectedLights) {
			canvasPanel.removeLight(light);
		}
	}
}